package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.templates.FaceTemplate;
import com.tanhua.commons.templates.HuanXinTemplate;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.RecommendUser;
import com.tanhua.domain.vo.*;
import com.tanhua.dubbo.api.UserApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.mongo.FriendApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 用户业务逻辑层
 */
@Service
@Slf4j
public class UserService {
    @Reference
    private UserApi userApi;

    @Reference
    private UserInfoApi userInfoApi;

    @Value("${tanhua.redisValidateCodeKeyPrefix}")
    private String redisValidateCodeKeyPrefix;
    
    @Autowired
    private SmsTemplate smsTemplate;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private FaceTemplate faceTemplate;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @Reference
    private UserLikeApi userLikeApi;

    @Reference
    private FriendApi friendApi;

    /**
     * 保存用户对象 返回UserId
     */
    public Long saveUser(String mobile, String password) {
        User user = new User();
        user.setPassword(password);
        user.setMobile(mobile);
        return userApi.save(user);
    }

    /**
     * 根据mobile查询user对象
     */
    public User findByMobile(String mobile) {
        return userApi.findByMobile(mobile);
    }

    /**
     * 注册-发送验证码
     */
    public void sendValidateCode(String phone) {

        String key = redisValidateCodeKeyPrefix+phone;
        //1.根据手机号码查询redis验证码是否存在
        Object o = redisTemplate.opsForValue().get(key);
        //2.如果存在，返回验证码还未失效
        if(o != null){
            //抛出异常
            throw new TanHuaException(ErrorResult.duplicate());
        }
        String validateCode = "123456";
        //String validateCode = RandomStringUtils.randomNumeric(6);
        log.debug("手机号码:{},验证码：{}",phone,validateCode);
        //3.如果不存在，调用阿里云发送短信
        if(false){
            Map<String, String> smRs = smsTemplate.sendValidateCode(phone, validateCode);
            if(smRs != null){
                //发送短信失败 返回not null
                throw new TanHuaException(ErrorResult.fail());
            }
        }
        //4.发送成功 将验证码写入redis
        redisTemplate.opsForValue().set(key,validateCode,5, TimeUnit.MINUTES);
        log.debug("发送验证码成功了，哈哈");
    }

    /**
     * 登录（自动注册）第二步---验证码校验
     */
    public Map<String,Object> loginVerification(String mobile, String verificationCode) {
        //定义返回结果Map
        Map<String,Object> rsMap = new HashMap<>();
        //定义是否新注册用户
        boolean flag = false;

        //1.根据手机号查询redis是否存在
        String key = redisValidateCodeKeyPrefix+mobile;
        Object o = redisTemplate.opsForValue().get(key);
        //2.如果redis记录不存在，告诉用户验证码失效了
        if(o == null){
            //抛出异常
            throw new TanHuaException(ErrorResult.loginError());
        }
        //3.验证码校验
        String redisCode = (String)o;
        if(StringUtils.isEmpty(verificationCode) && !verificationCode.equals(redisCode)){
            throw new TanHuaException(ErrorResult.validateCodeError());
        }
        //4.验证码校验成功 根据手机号码查询用户是否注册
        User user = userApi.findByMobile(mobile);
        //5.用户不存在，则注册用户
        if(user == null){
            user = new User();
            user.setMobile(mobile);
            user.setPassword(DigestUtils.md5Hex(mobile.substring(mobile.length()-6)));
            Long dbUserId = userApi.save(user);
            //set UserId 新注册用户 将userId设置到User对象中
            //为了生成token令牌需要参数
            user.setId(dbUserId);
            flag = true;
            //注册环信云
            huanXinTemplate.register(dbUserId);
            log.debug("环信云注册成功了。。。。");
        }
        //6.用户存在，则登录（生成token 存入redis 并返回登录信息）
        String token = jwtUtils.createJWT(mobile, user.getId());
        //7.key:TOKEN_token  Value值：将user对象以字符串形式存入redis
        String userStr = JSON.toJSONString(user);
        redisTemplate.opsForValue().set("TOKEN_"+token,userStr,1,TimeUnit.DAYS);
        rsMap.put("token",token);
        rsMap.put("isNew",flag);
        //8.删除redis
        redisTemplate.delete(key);
        return rsMap;
    }

    /**
     * 公共获取userToken方法
     */
    public User getUserByToken(String token){
        String userStr = redisTemplate.opsForValue().get("TOKEN_" + token);
        if(StringUtils.isEmpty(userStr)){
            return null;//没有获取到用户信息
        }
        //将UserStr 转为User对象
        User user = JSON.parseObject(userStr, User.class);
        if(user == null){
            return null;
        }
        //续签 +1
        redisTemplate.expire("TOKEN_" + token,1,TimeUnit.DAYS);
        return user;
    }

    /**
     * 完善个人信息-1
     */
    public void loginReginfo(UserInfoVo userInfoVo, String headToken) {
        log.debug("*******************完善个人信息-1:::"+UserHolder.getUserId());
        //1.从token中获取用户信息 如果获取不到，返回登录超时
        /*User user = getUserByToken(headToken);
        if(user == null){
            throw new TanHuaException(ErrorResult.loginTimeOut());
        }*/
        //2.将个人信息 保存用户UserInfo表(从UserInfoVO  和 User对象中获取的)
        UserInfo userInfo = new UserInfo();
        /*userInfo.setGender(userInfoVo.getGender());
        userInfo.setNickname(userInfoVo.getNickname());
        userInfo.setBirthday(userInfoVo.getBirthday());
        userInfo.setCity(userInfoVo.getCity());*/
        BeanUtils.copyProperties(userInfoVo,userInfo);
        userInfo.setId(UserHolder.getUserId());
        //从userInfoVo中copy属性名称一致的值 到userInfo对象中
        //如果两个实体对象 有不一样的属性 手动设置一次即可
        userInfoApi.save(userInfo);
    }

    /**
     * 完善个人信息-2  上传头像
     */
    public void loginReginfoHead(MultipartFile headPhoto, String headToken) {
        log.debug("*******************完善个人信息-2  上传头像:::"+UserHolder.getUserId());
        //a.根据Token获取User对象，如果不存在 登录超时
      /*  User user = getUserByToken(headToken);
        if(user == null){
            throw new TanHuaException(ErrorResult.loginTimeOut());
        }*/
        //创建userInfo
        UserInfo userInfo = new UserInfo();
        Long userId = UserHolder.getUserId();
        userInfo.setId(userId);
        //b.调用人脸识别接口 验证 成功往下执行 失败则直接返回错误
        try {
            boolean detect = faceTemplate.detect(headPhoto.getBytes());
            if(!detect){
                throw new TanHuaException(ErrorResult.faceError());
            }
        } catch (IOException e) {
            throw new TanHuaException(ErrorResult.faceError());
        }

        //c.调用阿里云OSS存储头像图片 成功往下执行  失败返回错误
        try {
            String originalFilename = headPhoto.getOriginalFilename();//原始文件名
            String urlHead = ossTemplate.upload(originalFilename,headPhoto.getInputStream());
            userInfo.setAvatar(urlHead);//设置头像
        } catch (IOException e) {
            e.printStackTrace();
            throw new TanHuaException(ErrorResult.uploadHeadFail());
        }
        //d.根据用户id更新头像地址信息。
        userInfoApi.update(userInfo);

    }

    /**
     * 互相喜欢，喜欢，粉丝 - 统计
     */
    public CountsVo counts() {
        return userLikeApi.counts(UserHolder.getUserId());
    }

    /**
     * 查询相互喜欢、我喜欢、粉丝列表分页查询
     * 1 互相关注
     * 2 我关注
     * 3 粉丝
     * 4 谁看过我
     */
    public PageResult<FriendVo> queryUserLikeList(int type, int page, int pagesize) {

        PageResult<FriendVo> friendVoPageResult = new PageResult<>();
        Long userId = UserHolder.getUserId();//当前登录用户id
        PageResult<RecommendUser> pageResult = new PageResult();
        switch (type){
            case 1:
                //1.判断type=1 根据userId查询好友表  互相喜欢列表
                pageResult = userLikeApi.findPageLikeEachOther(userId,page,pagesize);
                break;
            case 2:
                //2.判断type=2 根据userId查询UserLike 喜欢列表
                pageResult = userLikeApi.findPageOneSideLike(userId,page,pagesize);
                break;
            case 3:
                //3.判断type=3 根据userId查询UserLike 粉丝列表
                pageResult = userLikeApi.findPageFens(userId,page,pagesize);
                break;
            case 4:
                //4.判断type=4 根据userId查询visitors 谁看过我列表
                pageResult = userLikeApi.findPageMyVisitors(userId,page,pagesize);
                break;
            default: break;
        }
        if(pageResult == null || pageResult.getItems() == null || pageResult.getItems().size() == 0){
            return null;
        }
        //5.查询userInfo
        List<FriendVo> friendVoList = new ArrayList<>();
        for (RecommendUser recommendUser : pageResult.getItems()) {
            if(recommendUser == null){
                continue;
            }
            FriendVo friendVo = new FriendVo();
            Long recommendUserId = recommendUser.getUserId();//查询 相互喜欢、我喜欢、粉丝 用户信息
            UserInfo userInfo = userInfoApi.findByUserId(recommendUserId);
            BeanUtils.copyProperties(userInfo,friendVo);
            //设置缘分值
            if(recommendUser.getScore() != null) {
                friendVo.setMatchRate(recommendUser.getScore().intValue());
            }else
            {
                friendVo.setMatchRate(77);
            }
            friendVoList.add(friendVo);
        }
        //6.封装Vo返回
        BeanUtils.copyProperties(pageResult,friendVoPageResult);
        friendVoPageResult.setItems(friendVoList);
        return friendVoPageResult;
    }

    /**
     * 粉丝-喜欢
     * 请求连接：POST  /fans/:uid
     */
    public void fansLike(Long likeUserId) {
        Long userId = UserHolder.getUserId();//登录用户id
        //1.根据当前用户id 和 粉丝用户id  删除UserLike记录
        userLikeApi.delete(likeUserId,userId);
        //2.调用好友表 新增2条记录
        friendApi.addContacts(likeUserId,userId);
        //3.调用环信员makeFrineds
        huanXinTemplate.makeFriends(likeUserId,userId);
    }
}
